Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

225
Vistas
Upload a file to Amazon S3 with presigned url + PUT request but get error "SignatureDoesNotMatch" for "GET" in "StringToSign"

I am trying to upload files to Amazon S3 with a presigned url with javascript fetch() as following(copy past from the chrome Developer tool)

fetch("https://.....amazonaws.com/.../copy.mp3?AWSAccessKeyId=...&Signature=...&Expires=1631443785", {
  "headers": {
    "content-type": "audio/mpeg",
    "sec-ch-ua": "\"Google Chrome\";v=\"93\", \" Not;A Brand\";v=\"99\", \"Chromium\";v=\"93\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"macOS\""
  },
  "referrer": "http://localhost:3000/",
  "referrerPolicy": "strict-origin-when-cross-origin",
  "method": "PUT",
  "mode": "cors",
  "credentials": "omit"
});

and it returns the following error "SignatureDoesNotMatch":

<Error>
 <Code>SignatureDoesNotMatch</Code>
 <Message>The request signature we calculated does not match the signature you provided. 
 Check your key and signing method.</Message>
 <AWSAccessKeyId>...</AWSAccessKeyId>
 <StringToSign>GET 1631443785 ..../copy.mp3</StringToSign>
...
</Error>

The StringToSign in the error says it's a "GET" request while I think that I am sending a PUT with fetch().

Besides, I try to run $curl like:

$curl --request PUT --upload-file copy.mp3  https://....'

and it works.

Anything I am doing wrong here?

Thank you in advance.. I have been blocked here for 2 days :(

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

I figured out how to upload with POST request(instead of PUT, it's a workaround solution) and here is how:

For your brower:

const formData = new FormData();

Object.keys(signedPost.fields).forEach(key => {
    formData.append(key, signedPost.fields[key]);
});

// You must put the file in the last position otherwise S3 complains:
// "Bucket POST must contain a field named 'key'.  If it is specified, please check the order of the fields."
// If any people who works for Amazon S3 see this error msg, please fix it.. // It's confusing. Using E.g "Put file in the last position" instead.
formData.append("file", file);

fetch(
    signedPost.url,
    {
        method: "POST",
        body: formData,
    }
).then(
    res => console.log(res),
).catch((error) => {
    console.log(error);
    throw error;
});

For your server: Use the generate_presigned_post API instead of generate_presigned_url. E.g:

respone = s3_client.generate_presigned_post(
    Bucket=bucket,
    Key=key,
    ExpiresIn=expires_in_s,
)

My understanding of my original issues so far: For my original "SignatureDoesNotMatch" blocking pre-flight OPTIONS request issue, the post request skip the OPTIONS request. As a result, the post pre-signed workaround it. That's also why $curl + PUT works but javascript PUT in Chrome does not work for the exactly same pre-signed url for PUT requests. $curl doesn't run preflight OPTIONS. But for javascript in the Chrome, it runs (a) Send OPTIONS (b) Send PUT and I was blocked in (a). As the discussion in (1), someone fond almost same issue 7 years ago and we still don't have a good answer under that question. With a working post solution, I would let it go instead of burning more time on this. However, It would be great if someone from Amazon could create a ticket for it if necessary.

reference:

  • (1) here is a very similar issue but it is not exactly same.
  • (2) Presigned URLs Example from Amazon
  • (3) What's the difference between generate_presigned_post and generate_presigned_url?.
about 4 years ago · Juan Pablo Isaza Denunciar

0

There is an example on how to do this using fetch in the aws docs:


          // Import the required AWS SDK clients and commands for Node.js
import {
  CreateBucketCommand,
  DeleteObjectCommand,
  PutObjectCommand,
  DeleteBucketCommand }
from "@aws-sdk/client-s3";
import { s3Client } from "./libs/s3Client.js"; // Helper function that creates Amazon S3 service client module.
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import fetch from "node-fetch";

// Set parameters
// Create a random names for the Amazon Simple Storage Service (Amazon S3) bucket and key
export const bucketParams = {
  Bucket: `test-bucket-${Math.ceil(Math.random() * 10 ** 10)}`,
  Key: `test-object-${Math.ceil(Math.random() * 10 ** 10)}`,
  Body: "BODY"
};
export const run = async () => {
  try {
    // Create an Amazon S3 bucket.
    console.log(`Creating bucket ${bucketParams.Bucket}`);
    await s3Client.send(new CreateBucketCommand({ Bucket: bucketParams.Bucket }));
    console.log(`Waiting for "${bucketParams.Bucket}" bucket creation...`);
  } catch (err) {
    console.log("Error creating bucket", err);
  }
  try {
    // Create the command.
    const command = new PutObjectCommand(bucketParams);

    // Create the presigned URL.
    const signedUrl = await getSignedUrl(s3Client, command, {
      expiresIn: 3600,
    });
    console.log(
      `\nPutting "${bucketParams.Key}" using signedUrl with body "${bucketParams.Body}" in v3`
    );
    console.log(signedUrl);
    const response = await fetch(signedUrl);
    console.log(
      `\nResponse returned by signed URL: ${await response.text()}\n`
    );
    return response;
  } catch (err) {
    console.log("Error creating presigned URL", err);
  }
  try {
    // Delete the object.
    console.log(`\nDeleting object "${bucketParams.Key}"} from bucket`);
    await s3Client.send(
      new DeleteObjectCommand({ Bucket: bucketParams.Bucket, Key: bucketParams.Key })
    );
  } catch (err) {
    console.log("Error deleting object", err);
  }
  try {
    // Delete the Amazon S3 bucket.
    console.log(`\nDeleting bucket ${bucketParams.Bucket}`);
    await s3.send(new DeleteBucketCommand({ Bucket: bucketParams.Bucket }));
  } catch (err) {
    console.log("Error deleting bucket", err);
  }
};
run();

It's a bit more than you need probably. More info here

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda